package JavaUtils.CSUtils;

import JavaUtils.CSUtils.Log.CLog;
import JavaUtils.weData.We_DataBase;

import java.lang.Object;
import java.nio.charset.StandardCharsets;
import java.util.ArrayList;
import java.util.List;
import java.util.Map;

public class BinaryReader {
    static final String tag = "BinaryReader";
    public int readerIndex;
    public int Length;
    public byte[] buf;

    public BinaryReader(byte[] buf) {
        this.buf = buf;
        Length = buf.length;
    }

    public boolean ReadBoolean() {
        int ii = (this.buf[this.readerIndex++] & 0xFF);
        return ii == 1;
    }

    public byte ReadByte() {
        return (byte) (this.buf[this.readerIndex++] & 0xFF);
    }

    public char ReadChar() {
        return (char) (this.buf[this.readerIndex++] & 0xFF);
    }

    public short ReadInt16() {
        return (short) (((this.buf[this.readerIndex++] & 0xFF) << 8) + (this.buf[this.readerIndex++] & 0xFF));
    }

    public int ReadUInt16() {
        return (int) (((this.buf[this.readerIndex++] & 0xFF) << 8) + (this.buf[this.readerIndex++] & 0xFF));
    }

    public int ReadInt32() {
        return ((this.buf[this.readerIndex++] & 0xFF) << 24)
                + ((this.buf[this.readerIndex++] & 0xFF) << 16)
                + ((this.buf[this.readerIndex++] & 0xFF) << 8)
                + ((this.buf[this.readerIndex++] & 0xFF));
    }

    public long ReadUInt32() {
        return ((this.buf[this.readerIndex++] & 0xFF) << 24)
                + ((this.buf[this.readerIndex++] & 0xFF) << 16)
                + ((this.buf[this.readerIndex++] & 0xFF) << 8)
                + ((this.buf[this.readerIndex++] & 0xFF));
    }

    public float ReadFloat() {
        return Float.intBitsToFloat(ReadInt32());
    }

    public long ReadInt64() {
        return (((long) this.buf[this.readerIndex++] << 56)
                + ((long) (this.buf[this.readerIndex++] & 0xFF) << 48)
                + ((long) (this.buf[this.readerIndex++] & 0xFF) << 40)
                + ((long) (this.buf[this.readerIndex++] & 0xFF) << 32)
                + ((long) (this.buf[this.readerIndex++] & 0xFF) << 24)
                + ((this.buf[this.readerIndex++] & 0xFF) << 16)
                + ((this.buf[this.readerIndex++] & 0xFF) << 8)
                + ((this.buf[this.readerIndex++] & 0xFF)));
    }

    public long ReadUInt64() {
        return (((long) this.buf[this.readerIndex++] << 56)
                + ((long) (this.buf[this.readerIndex++] & 0xFF) << 48)
                + ((long) (this.buf[this.readerIndex++] & 0xFF) << 40)
                + ((long) (this.buf[this.readerIndex++] & 0xFF) << 32)
                + ((long) (this.buf[this.readerIndex++] & 0xFF) << 24)
                + ((this.buf[this.readerIndex++] & 0xFF) << 16)
                + ((this.buf[this.readerIndex++] & 0xFF) << 8)
                + ((this.buf[this.readerIndex++] & 0xFF)));
    }


    public double ReadDouble() {
        return Double.longBitsToDouble(ReadInt64());
    }

    public byte[] ReadBytes() {
        int length = ReadInt32();
        byte[] newBuf = new byte[length];
        System.arraycopy(buf, this.readerIndex, newBuf, 0, length);
        return newBuf;
    }

    public String ReadString() {
        short length0 = ReadInt16();
        int length = length0 & 0xFF;
        byte[] newBuf = new byte[length];
        System.arraycopy(buf, this.readerIndex, newBuf, 0, length);
        return new String(newBuf, StandardCharsets.UTF_8);
    }

    public CInt4 ReadCInt4() {
        byte length = ReadByte();
        if (length == 0) {
            return null;
        } else if (length == 1) {
            int id = ReadInt32();
            return CInt4.Get(id, false);
        } else if (length == 4) {
            int aa = ReadInt32();
            int bb = ReadInt32();
            int cc = ReadInt32();
            int dd = ReadInt32();
            return CInt4.Get(aa, bb, cc, dd);
        } else {
            CLog.ef(tag, "We读取C_Int4.出错...length != 4");
            return null;
        }
    }

    public <T> List<T[]> S_ReadByteArrayArray(int subType, Map<Integer, We_DataBase> uintObjDic) {
        int subType0 = ReadByte();
        if (subType0 != subType) {
            CLog.ef(tag, "错误....列表子类型不同_____________{0}._____{1}", subType0, subType);
        }

        List<T[]> list = new ArrayList<T[]>();
        long langth = ReadUInt32();
        if (langth == 0) {
            return null;
        }
        long endPosition = readerIndex + langth;
        while (readerIndex < endPosition) {
            T[] arr = (T[]) S_ReadByteArray(subType, uintObjDic);
            list.add(arr);
        }
        return list;
    }

    public Object[] S_ReadByteArray(int subType, Map<Integer, We_DataBase> uintObjDic) {
        int subType0 = ReadByte();
        if (subType0 != subType) {
            CLog.ef(tag, "错误....列表子类型不同_____________{0}._____{1}", subType0, subType);
        }

        List<Object> list = new ArrayList<Object>();
        long langth = ReadUInt32();
        if (langth == 0) {
            return null;
        }
        long endPosition = readerIndex + langth;
        while (readerIndex < endPosition) {
            Object tt = S_ReadByteObj(subType, uintObjDic);
            list.add(tt);
        }
        return list.toArray();
    }

    public java.lang.Object S_ReadByteObj(int baseType, Map<Integer, We_DataBase> uintObjDic) {
        switch (baseType) {
            case EBaseType.e001_bool:
                return ReadBoolean();
            case EBaseType.e003_byte:
                return ReadByte();
            case EBaseType.e004_short:
                return ReadInt16();
            case EBaseType.e005_ushort:
                return ReadUInt16();
            case EBaseType.e006_int:
                return ReadInt32();
            case EBaseType.e007_uint:
                return ReadUInt32();
            case EBaseType.e008_float:
                return ReadFloat();
            case EBaseType.e009_double:
                return ReadDouble();
            case EBaseType.e010_long:
                return ReadInt64();
            case EBaseType.e011_ulong:
                return ReadUInt64();
            case EBaseType.e012_string:
                return ReadString();
            case EBaseType.e013_Byte4:
                return ReadCInt4();
            case EBaseType.e014_Int4:
                return ReadCInt4();
            case EBaseType.e017_Enum:
                return ReadInt16();
            case EBaseType.e018_array:
            case EBaseType.e026_list:
            case EBaseType.e037_dic:
            case EBaseType.e020_obj:
                CLog.ex(tag, "---数组不能直接调用这个方法10");
                return null;
            case EBaseType.e021_weData:
                int instanceId = ReadInt32();
                if (!uintObjDic.containsKey(instanceId)) {
                    return null;
                }
                return uintObjDic.get(instanceId);
        }
        return null;
    }


}
